﻿Imports System.Diagnostics
Imports System.Drawing
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.ComponentModel






''' <summary>
''' 捕获键盘鼠标所有事件
''' 模拟鼠标和模拟键盘操作
'''  老外写的一个C#钩子类，写的非常好。
''' </summary>
Public Class vbnet_hook

#Region "API声明"
    ''' <summary>
    ''' HookProc 钩子处理过程
    ''' </summary>
    ''' <param name="code"></param>
    ''' <param name="wParam"></param>
    ''' <param name="lParam"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)> _
    Protected Delegate Function HookProc(ByVal code As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer

    Protected Enum HookType As Integer
        ''' <summary>
        '''	安装钩子程序，在系统将消息发送到目标窗口过程之前监视消息。有关更多信息，请参阅CallWndProc挂钩过程。
        ''' </summary>
        WH_CALLWNDPROC = 4
        ''' <summary>
        '''	安装钩子程序，在目标窗口过程处理消息后监视消息。有关更多信息，请参阅CallWndRetProc挂钩过程。
        ''' </summary>
        WH_CALLWNDPROCRET = 12
        ''' <summary>
        '''	安装钩子程序，接收对基于计算机的培训（CBT）应用程序有用的通知。有关更多信息，请参阅CBTProc挂钩过程。
        ''' </summary>
        WH_CBT = 5
        ''' <summary>
        '''	安装可用于调试其他挂钩程序的挂钩程序。有关更多信息，请参阅DebugProc挂钩过程。
        ''' </summary>
        WH_DEBUG = 9
        ''' <summary>
        '''	安装将在应用程序的前台线程即将变为空闲时调用的钩子过程。该挂钩对于在空闲时执行低优先级任务很有用。有关更多信息，请参阅ForegroundIdleProc挂钩过程。
        ''' </summary>
        WH_FOREGROUNDIDLE = 11
        ''' <summary>
        '''	安装一个监视发送到消息队列的消息的挂钩过程。有关更多信息，请参阅GetMsgProc挂钩过程。
        ''' </summary>
        WH_GETMESSAGE = 3
        ''' <summary>
        '''	安装一个挂钩过程，用于发布先前由WH_JOURNALRECORD挂钩过程记录的消息。有关更多信息，请参阅JournalPlaybackProc挂钩过程。
        ''' </summary>
        WH_JOURNALPLAYBACK = 1
        ''' <summary>
        '''	安装一个挂钩过程，记录发布到系统消息队列的输入消息。这个钩子对于录制宏很有用。有关更多信息，请参阅JournalRecordProc挂钩过程。
        ''' </summary>
        WH_JOURNALRECORD = 0
        ''' <summary>
        '''	安装监视按键消息的挂钩过程。有关更多信息，请参阅KeyboardProc挂钩过程。
        ''' </summary>
        WH_KEYBOARD = 2
        ''' <summary>
        '''	Windows NT / 2000 / XP：安装监视低级键盘输入事件的挂钩程序。有关更多信息，请参阅LowLevelKeyboardProc挂钩过程。
        ''' </summary>
        WH_KEYBOARD_LL = 13
        ''' <summary>
        '''	安装监视鼠标消息的挂钩过程。有关更多信息，请参阅MouseProc挂钩过程。
        ''' </summary>
        WH_MOUSE = 7
        ''' <summary>
        '''	Windows NT / 2000 / XP：安装监视低级别鼠标输入事件的挂钩程序。有关更多信息，请参阅LowLevelMouseProc挂钩过程。
        ''' </summary>
        WH_MOUSE_LL = 14
        ''' <summary>
        '''	安装钩子程序，用于监视在对话框，消息框，菜单或滚动条中由于输入事件而生成的消息。有关更多信息，请参阅MessageProc挂钩过程。
        ''' </summary>
        WH_MSGFILTER = -1
        ''' <summary>
        '''	安装接收对shell应用程序有用的通知的挂钩程序。有关更多信息，请参阅ShellProc挂钩过程。
        ''' </summary>
        WH_SHELL = 10
        ''' <summary>
        '''	安装钩子程序，用于监视在对话框，消息框，菜单或滚动条中由于输入事件而生成的消息。钩子程序监视与调用线程相同的桌面中的所有应用程序的这些消息。有关更多信息，请参阅SysMsgProc挂钩过程。
        ''' </summary>
        WH_SYSMSGFILTER = 6
    End Enum

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)>
    Protected Shared Function SetWindowsHookEx(idHook As Integer, lpfn As HookProc, hMod As IntPtr, dwThreadId As Integer) As Integer
    End Function

    <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
    Private Shared Function GetModuleHandle(modulename As [String]) As IntPtr
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
    Private Shared Function SetWindowsHookExW(idHook As Integer, lpfn As HookProc, hmod As IntPtr, dwThreadID As UInteger) As IntPtr
    End Function


    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)>
    Protected Shared Function UnhookWindowsHookEx(idHook As Integer) As Integer
    End Function


    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
    Protected Shared Function CallNextHookEx(idHook As Integer, nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer
    End Function

    <DllImport("user32")>
    Protected Shared Function ToAscii(uVirtKey As Integer, uScanCode As Integer, lpbKeyState As Byte(), lpwTransKey As Byte(), fuState As Integer) As Integer
    End Function

    <DllImport("user32")>
    Protected Shared Function GetKeyboardState(pbKeyState As Byte()) As Integer
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
    Protected Shared Function GetKeyState(vKey As Integer) As Short
    End Function



#End Region
   

    
  
#Region "定义结构"
    ''' <summary>
    ''' 定义点的结构
    ''' </summary>
    Protected Structure POINT
        Dim x As Integer
        Dim y As Integer
    End Structure
    ''' <summary>
    ''' 鼠标消息结构
    ''' </summary>
    Protected Structure MouseHookStruct
        Dim PT As POINT
        Dim Hwnd As Integer
        Dim WHitTestCode As Integer
        Dim DwExtraInfo As Integer
    End Structure

    Protected Structure MouseLLHookStruct
        Dim PT As POINT
        Dim MouseData As Integer
        Dim Flags As Integer
        Dim Time As Integer
        Dim DwExtraInfo As Integer
    End Structure

    ''' <summary>
    ''' 键盘消息结构
    ''' </summary>
    ''' <remarks></remarks>
    Protected Structure KeyboardHookStruct
        ''' <summary>
        ''' 1到254间的虚似键盘码
        ''' </summary>
        Dim vkCode As Integer
        ''' <summary>
        ''' 扫描码
        ''' </summary>
        Dim ScanCode As Integer
        Dim Flags As Integer
        Dim Time As Integer
        Dim DwExtraInfo As Integer
    End Structure

#End Region

#Region "定义常量"
    Protected Const WM_MOUSEMOVE As Integer = &H200
    Protected Const WM_LBUTTONDOWN As Integer = &H201
    Protected Const WM_LBUTTONUP As Integer = &H202
    Protected Const WM_LBUTTONDBLCLK As Integer = &H203

    Protected Const WM_RBUTTONDOWN As Integer = &H204
    Protected Const WM_RBUTTONUP As Integer = &H205
    Protected Const WM_RBUTTONDBLCLK As Integer = &H206

    Protected Const WM_MBUTTONDOWN As Integer = &H207
    Protected Const WM_MBUTTONUP As Integer = &H208
    Protected Const WM_MBUTTONDBLCLK As Integer = &H209
    Protected Const WM_MOUSEWHEEL As Integer = &H20A

    Protected Const WM_KEYDOWN As Integer = &H100
    Protected Const WM_KEYUP As Integer = &H101
    Protected Const WM_SYSKEYDOWN As Integer = &H104
    Protected Const WM_SYSKEYUP As Integer = &H105

    Protected Const WM_NCMOUSEMOVE = &HA0
    Protected Const WM_NCLBUTTONDOWN = &HA1
    Protected Const WM_NCLBUTTONUP = &HA2
    Protected Const WM_NCLBUTTONDBLCLK = &HA3
    Protected Const WM_NCRBUTTONDOWN = &HA4
    Protected Const WM_NCRBUTTONUP = &HA5
    Protected Const WM_NCRBUTTONDBLCLK = &HA6
    Protected Const WM_NCMBUTTONDOWN = &HA7
    Protected Const WM_NCMBUTTONUP = &HA8
    Protected Const WM_NCMBUTTONDBLCLK = &HA9
    Protected Const WM_NCXBUTTONDOWN = &HAB
    Protected Const WM_NCXBUTTONUP = &HAC
    Protected Const WM_NCXBUTTONDBLCLK = &HAD
    ''' <summary>
    ''' SHIFT键
    ''' </summary>
    Protected Const VK_SHIFT As Byte = &H10
    ''' <summary>
    '''大小写键 CAPS LOCK 键
    ''' </summary>
    Protected Const VK_CAPITAL As Byte = &H14
    ''' <summary>
    ''' NUM LOCK 键
    ''' </summary>
    Protected Const VK_NUMLOCK As Byte = &H90

    Protected Const VK_LSHIFT As Byte = &HA0
    Protected Const VK_RSHIFT As Byte = &HA1
    ''' <summary>
    ''' Left CTRL
    ''' </summary>
    Protected Const VK_LCONTROL As Byte = &HA2
    ''' <summary>
    ''' Right CTRL
    ''' </summary>
    Protected Const VK_RCONTROL As Byte = &H3
    ''' <summary>
    ''' Left ALT
    ''' </summary>
    Protected Const VK_LALT As Byte = &HA4
    ''' <summary>
    ''' Right ALT
    ''' </summary>
    Protected Const VK_RALT As Byte = &HA5
#End Region

#Region "定义私有变量"

    Private hMouseHook As Integer
    Private hKeyboardHook As Integer

    Private Shared MouseHookProcedure As HookProc
    Private Shared KeyboardHookProcedure As HookProc

#End Region

#Region "创建与析构类型"

    ''' <summary>创建一个全局鼠标键盘钩子 (请使用Start方法开始监视)</summary>
    Sub New()
        '留空即可
        AddHandler Application.ApplicationExit, AddressOf Application_ApplicationExit
    End Sub
    ''' <summary>创建一个全局鼠标键盘钩子，决定是否安装钩子</summary>
    ''' <param name="InstallAll">是否立刻挂钩系统消息</param>
    Sub New(ByVal InstallAll As Boolean)
        If InstallAll Then Start(True, True)
        AddHandler Application.ApplicationExit, AddressOf Application_ApplicationExit
    End Sub
    ''' <summary>创建一个全局鼠标键盘钩子，并决定安装钩子的类型</summary>
    ''' <param name="InstallKeyboard">挂钩键盘消息</param>
    ''' <param name="InstallMouse">挂钩鼠标消息</param>
    Sub New(ByVal InstallKeyboard As Boolean, ByVal InstallMouse As Boolean)
        Start(InstallKeyboard, InstallMouse)
        AddHandler Application.ApplicationExit, AddressOf Application_ApplicationExit
    End Sub
    ''' <summary>析构函数</summary>
    Protected Overrides Sub Finalize()
        UnHook() '卸载对象时反注册系统钩子
        MyBase.Finalize()
    End Sub

#End Region

#Region "注册和注销钩子"
    ''' <summary>开始安装系统钩子</summary>
    ''' <param name="InstallKeyboardHook">挂钩键盘消息</param>
    ''' <param name="InstallMouseHook">挂钩鼠标消息</param>
    Public Sub Start(Optional ByVal InstallKeyboardHook As Boolean = True, Optional ByVal InstallMouseHook As Boolean = False)
        '注册键盘钩子
        If InstallKeyboardHook AndAlso hKeyboardHook = 0 Then
            KeyboardHookProcedure = New HookProc(AddressOf KeyboardHookProc)
            Using curPro As Process = Process.GetCurrentProcess()
                Using curMod As ProcessModule = curPro.MainModule
                    hKeyboardHook = CInt(SetWindowsHookExW(HookType.WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(curMod.ModuleName), 0))
                End Using
            End Using
            If hKeyboardHook = 0 Then '检测是否注册完成
                UnHook(True, False) '在这里反注册
                Throw New Win32Exception(Marshal.GetLastWin32Error) '报告错误
            End If
        End If
        '注册鼠标钩子
        If InstallMouseHook AndAlso hMouseHook = 0 Then
            MouseHookProcedure = New HookProc(AddressOf MouseHookProc)
            Using curPro As Process = Process.GetCurrentProcess()
                Using curMod As ProcessModule = curPro.MainModule
                    hMouseHook = CInt(SetWindowsHookExW(HookType.WH_MOUSE_LL, MouseHookProcedure, GetModuleHandle(curMod.ModuleName), 0))
                End Using
            End Using
            If hMouseHook = 0 Then
                UnHook(False, True)
                Throw New Win32Exception(Marshal.GetLastWin32Error)
            End If
        End If
    End Sub
    ''' <summary>立刻卸载系统钩子</summary>
    ''' <param name="UninstallKeyboardHook">卸载键盘钩子</param>
    ''' <param name="UninstallMouseHook">卸载鼠标钩子</param>
    ''' <param name="ThrowExceptions">是否报告错误</param>
    Public Sub UnHook(Optional ByVal UninstallKeyboardHook As Boolean = True, Optional ByVal UninstallMouseHook As Boolean = True, Optional ByVal ThrowExceptions As Boolean = False)
        '卸载键盘钩子
        If hKeyboardHook <> 0 AndAlso UninstallKeyboardHook Then
            Dim retKeyboard As Integer = UnhookWindowsHookEx(hKeyboardHook)
            hKeyboardHook = 0 '恢复为初始值0
            If ThrowExceptions AndAlso retKeyboard = 0 Then '如果出现错误，是否报告错误
                Throw New Win32Exception(Marshal.GetLastWin32Error) '报告错误
            End If
        End If
        '卸载鼠标钩子
        If hMouseHook <> 0 AndAlso UninstallMouseHook Then
            Dim retMouse As Integer = UnhookWindowsHookEx(hMouseHook)
            hMouseHook = 0 '恢复为初始值0
            If ThrowExceptions AndAlso retMouse = 0 Then
                Throw New Win32Exception(Marshal.GetLastWin32Error)
            End If
        End If
    End Sub
   
    ''' <summary>
    ''' 程序退出方法
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Protected Sub Application_ApplicationExit(sender As Object, e As EventArgs)

        If hMouseHook <> 0 Then
            UnHook()
        End If
        If hKeyboardHook <> 0 Then
            UnHook()
        End If
    End Sub
#End Region


#Region "键盘钩子类"
    Private KeyboardEvent As New System.ComponentModel.EventHandlerList
#Region "类事件，键盘事件委托处理"
    ''' <summary>键盘按下事件</summary>
    Public Custom Event KeyDown As KeyEventHandler
        AddHandler(ByVal value As KeyEventHandler)
            KeyboardEvent.AddHandler("KeyDown", value)
        End AddHandler
        RemoveHandler(ByVal value As KeyEventHandler)
            KeyboardEvent.RemoveHandler("KeyDown", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)
            Dim eh As KeyEventHandler = TryCast(KeyboardEvent("KeyDown"), KeyEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event
    ''' <summary>键盘输入事件</summary>
    Public Custom Event KeyPress As KeyPressEventHandler
        AddHandler(ByVal value As KeyPressEventHandler)
            KeyboardEvent.AddHandler("KeyPress", value)
        End AddHandler
        RemoveHandler(ByVal value As KeyPressEventHandler)
            KeyboardEvent.RemoveHandler("KeyPress", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
            Dim eh As KeyPressEventHandler = TryCast(KeyboardEvent("KeyPress"), KeyPressEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event
    ''' <summary>键盘松开事件</summary>
    Public Custom Event KeyUp As KeyEventHandler
        AddHandler(ByVal value As KeyEventHandler)
            KeyboardEvent.AddHandler("KeyUp", value)
        End AddHandler
        RemoveHandler(ByVal value As KeyEventHandler)
            KeyboardEvent.RemoveHandler("KeyUp", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)
            Dim eh As KeyEventHandler = TryCast(KeyboardEvent("KeyUp"), KeyEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event
#End Region

#Region "类方法"

    ''' <summary>
    '''HookCallbackProcedure 钩子回调函数
    ''' </summary>
    ''' <param name="nCode"></param>
    ''' <param name="wParam"></param>
    ''' <param name="lParam"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Protected Function KeyboardHookProc(nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer

        Dim handled As Boolean = False

        If nCode > -1 AndAlso (KeyboardEvent("KeyDown") IsNot Nothing OrElse KeyboardEvent("KeyUp") IsNot Nothing OrElse KeyboardEvent("KeyPress") IsNot Nothing) Then

            Dim keyboardHookStruct As KeyboardHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(KeyboardHookStruct)), KeyboardHookStruct)

            '判断控制是否被按住了， Is Control being held down?  
            Dim control As Boolean = ((GetKeyState(VK_LCONTROL) And &H80) <> 0) OrElse ((GetKeyState(VK_RCONTROL) And &H80) <> 0)

            ' shift键是否被按下。Is Shift being held down?  
            Dim shift As Boolean = ((GetKeyState(VK_LSHIFT) And &H80) <> 0) OrElse ((GetKeyState(VK_RSHIFT) And &H80) <> 0)

            'alt键是否被按下。 Is Alt being held down?  
            Dim alt As Boolean = ((GetKeyState(VK_LALT) And &H80) <> 0) OrElse ((GetKeyState(VK_RALT) And &H80) <> 0)

            '大小写键是否被按下。 Is CapsLock on?  
            Dim capslock As Boolean = (GetKeyState(VK_CAPITAL) <> 0)

            ' 使用上面找到的keycode和control/shift/alt值创建事件。Create event using keycode and control/shift/alt values found above  
            Dim e As New KeyEventArgs(DirectCast(keyboardHookStruct.vkCode Or (If(control, CInt(Keys.Control), 0)) Or (If(shift, CInt(Keys.Shift), 0)) Or (If(alt, CInt(Keys.Alt), 0)), Keys))

            ' 处理KeyDown和KeyUp事件。Handle KeyDown and KeyUp events  
            Select Case wParam

                Case WM_KEYDOWN, WM_SYSKEYDOWN
                    If KeyboardEvent("KeyDown") IsNot Nothing Then
                        RaiseEvent KeyDown(Me, e)
                        handled = handled OrElse e.Handled
                    End If
                    Exit Select
                Case WM_KEYUP, WM_SYSKEYUP
                    If KeyboardEvent("KeyUp") IsNot Nothing Then
                        RaiseEvent KeyUp(Me, e)
                        handled = handled OrElse e.Handled
                    End If
                    Exit Select

            End Select

            ' 处理按住事件。Handle KeyPress event  
            If wParam = WM_KEYDOWN AndAlso Not handled AndAlso Not e.SuppressKeyPress AndAlso KeyboardEvent("KeyPress") IsNot Nothing Then

                Dim keyState As Byte() = New Byte(255) {}
                Dim inBuffer As Byte() = New Byte(1) {}
                GetKeyboardState(keyState)

                If ToAscii(keyboardHookStruct.vkCode, keyboardHookStruct.ScanCode, keyState, inBuffer, keyboardHookStruct.Flags) = 1 Then

                    '	Dim key As Char = CChar(inBuffer(0))'修改为下面的句子。
                    Dim key As Char : key = Chr(inBuffer(0))
                    If (capslock Xor shift) AndAlso [Char].IsLetter(key) Then
                        key = [Char].ToUpper(key)
                    End If
                    Dim e2 As New KeyPressEventArgs(key)
                    RaiseEvent KeyPress(Me, e2)

                    handled = handled OrElse e.Handled

                End If

            End If
        End If

        If handled Then
            Return 1
        Else
            Return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam)
        End If

    End Function

#End Region



#End Region

#Region "鼠标钩子类"
    Private MouseEvent As New System.ComponentModel.EventHandlerList
#Region "MouseEventType Enum"
    Private Enum MouseEventType
        ''' <summary>
        ''' 无鼠标事件
        ''' </summary>
        None
        ''' <summary>
        ''' 鼠标按下
        ''' </summary>
        MouseDown
        ''' <summary>
        ''' 鼠标抬起
        ''' </summary>
        MouseUp
        ''' <summary>
        ''' 双击鼠标
        ''' </summary>
        DoubleClick
        ''' <summary>
        ''' 鼠标滚轮事件
        ''' </summary>
        MouseWheel
        ''' <summary>
        ''' 鼠标移动事件
        ''' </summary>
        MouseMove
    End Enum
#End Region

#Region "类事件，鼠标事件_Events"
    ''' <summary>鼠标按下事件</summary>
    Public Custom Event MouseDown As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            MouseEvent.AddHandler("MouseDown", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            MouseEvent.RemoveHandler("MouseDown", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(MouseEvent("MouseDown"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标松开事件</summary>
    Public Custom Event MouseUp As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            MouseEvent.AddHandler("MouseUp", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            MouseEvent.RemoveHandler("MouseUp", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(MouseEvent("MouseUp"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标移动事件</summary>
    Public Custom Event MouseMove As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            MouseEvent.AddHandler("MouseMove", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            MouseEvent.RemoveHandler("MouseMove", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(MouseEvent("MouseMove"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event


    ''' <summary>鼠标滚轮事件</summary>
    Public Custom Event MouseWheel As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            MouseEvent.AddHandler("MouseWheel", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            MouseEvent.RemoveHandler("MouseWheel", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(MouseEvent("MouseWheel"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标单击事件</summary>
    Public Custom Event Click As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            MouseEvent.AddHandler("Click", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            MouseEvent.RemoveHandler("Click", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(MouseEvent("Click"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标双击事件</summary>
    Public Custom Event DoubleClick As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            MouseEvent.AddHandler("DoubleClick", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            MouseEvent.RemoveHandler("DoubleClick", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(MouseEvent("DoubleClick"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event
#End Region

#Region "Methods"
    ''' <summary>
    ''' 钩子回调函数
    ''' </summary>
    ''' <param name="nCode"></param>
    ''' <param name="wParam"></param>
    ''' <param name="lParam"></param>
    ''' <returns></returns>
    Protected Function MouseHookProc(nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer

        If nCode > -1 AndAlso (MouseEvent("MouseDown") IsNot Nothing OrElse MouseEvent("MouseUp") IsNot Nothing OrElse MouseEvent("MouseMove") IsNot Nothing) Then

            Dim mouseHookStruct As MouseLLHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(MouseLLHookStruct)), MouseLLHookStruct)

            Dim button As MouseButtons = GetButton(wParam)
            Dim eventType As MouseEventType = GetEventType(wParam) '定义的鼠标事件类型

            ' Dim e As New MouseEventArgs(button, (If(eventType = MouseEventType.DoubleClick, 2, 1)), mouseHookStruct.pt.x, mouseHookStruct.pt.y, (If(eventType = MouseEventType.MouseWheel, CShort((mouseHookStruct.mouseData >> 16) And &HFFFF), 0)))



            '******************改写成上面的Dim e As New MouseEventArgs语句和if语句如下：
            'If eventType = MouseEventType.DoubleClick Then
            '    eventType = 2
            'Else
            '    eventType = 1
            'End If

            ''本段代码CLE添加，模仿C#的Short从Int弃位转换
            Static int As Integer : int = (mouseHookStruct.MouseData >> 16) And &HFFFF '定义一个静态变量

            If eventType = MouseEventType.MouseWheel Then
                If int > Short.MaxValue Then mouseHookStruct.MouseData = int - 65536 Else mouseHookStruct.MouseData = int
            Else
                mouseHookStruct.MouseData = 0
            End If
            'MouseWheel这个事件不好用。干扰滚动放大缩小的问题。
            ' Dim e As New MouseEventArgs(button, (If(eventType = MouseEventType.DoubleClick, 2, 1)), mouseHookStruct.PT.x, mouseHookStruct.PT.y, mouseHookStruct.MouseData)
            '这个去了MouseWheel事件。
            Dim e As New MouseEventArgs(button, (If(eventType = MouseEventType.DoubleClick, 2, 1)), mouseHookStruct.PT.x, mouseHookStruct.PT.y, 0)
            '原函数构造函数MouseEventArgs(MouseButtons, Int32, Int32, Int32, Int32)
            '  button()  '获取曾按下的是哪个鼠标按钮。
            '  Clicks()            '获取按下并释放鼠标按钮的次数。
            ' Delta()            '获取鼠标轮已转动的制动器数的有符号计数乘以 WHEEL_DELTA 常数。 制动器是鼠标轮的一个凹口。
            ' Location()            '获取鼠标在产生鼠标事件时的位置。
            '  X()            '获取鼠标在产生鼠标事件时的 x 坐标。           
            'Y()            '获取鼠标在产生鼠标事件时的 y 坐标。
            '  Dim e As MouseEventArgs = New MouseEventArgs(button, eventType, mouseHookStruct.pt.x, mouseHookStruct.pt.y, mouseHookStruct.mouseData)

            '*************************改写完毕。



            ' 防止多个右键事件，Prevent multiple Right Click events (这可能发生在弹出式菜单)  
            If button = MouseButtons.Right AndAlso mouseHookStruct.Flags <> 0 Then
                eventType = MouseEventType.None
            End If

            Select Case eventType
                Case MouseEventType.MouseDown
                    RaiseEvent MouseDown(Me, e)

                    Exit Select
                Case MouseEventType.MouseUp
                    RaiseEvent Click(Me, e)
                    RaiseEvent MouseUp(Me, e)
                    Exit Select
                Case MouseEventType.DoubleClick
                    RaiseEvent DoubleClick(Me, e)
                    Exit Select
                Case MouseEventType.MouseWheel
                    RaiseEvent MouseWheel(Me, e)
                    Exit Select
                Case MouseEventType.MouseMove
                    RaiseEvent MouseMove(Me, e)
                    Exit Select
                Case Else
                    Exit Select

            End Select
        End If

        Return CallNextHookEx(hMouseHook, nCode, wParam, lParam)

    End Function

    Private Function GetButton(wParam As Int32) As MouseButtons

        Select Case wParam

            Case WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK
                Return MouseButtons.Left
            Case WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK
                Return MouseButtons.Right
            Case WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MBUTTONDBLCLK
                Return MouseButtons.Middle
            Case Else
                Return MouseButtons.None

        End Select

    End Function

    Private Function GetEventType(wParam As Int32) As MouseEventType

        Select Case wParam

            Case WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN
                Return MouseEventType.MouseDown
            Case WM_LBUTTONUP, WM_RBUTTONUP, WM_MBUTTONUP
                Return MouseEventType.MouseUp
            Case WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK
                Return MouseEventType.DoubleClick
            Case WM_MOUSEWHEEL
                Return MouseEventType.MouseWheel
            Case WM_MOUSEMOVE
                Return MouseEventType.MouseMove
            Case Else
                Return MouseEventType.None

        End Select
    End Function

#End Region





#End Region

End Class






#Region "键盘鼠标钩子--原型--上面是修改过的"


Public MustInherit Class GlobalHook
    '
    '     * 老外写的一个C#钩子类，写的非常好。
    '     * 捕获键盘鼠标所有事件
    '     * 模拟鼠标和模拟键盘操作
    '     * 
    '     * 

    ''' <summary>  
    ''' 鼠标和键盘钩子的抽象类
    ''' </summary>  
#Region "Windows API Code"

    <StructLayout(LayoutKind.Sequential)>
    Protected Class POINT
        Public x As Integer
        Public y As Integer
    End Class

    <StructLayout(LayoutKind.Sequential)>
    Protected Class MouseHookStruct
        Public pt As POINT
        Public hwnd As Integer
        Public wHitTestCode As Integer
        Public dwExtraInfo As Integer
    End Class

    <StructLayout(LayoutKind.Sequential)>
    Protected Class MouseLLHookStruct
        Public pt As POINT
        Public mouseData As Integer
        Public flags As Integer
        Public time As Integer
        Public dwExtraInfo As Integer
    End Class

    <StructLayout(LayoutKind.Sequential)>
    Protected Class KeyboardHookStruct
        Public vkCode As Integer
        Public scanCode As Integer
        Public flags As Integer
        Public time As Integer
        Public dwExtraInfo As Integer
    End Class

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)>
    Protected Shared Function SetWindowsHookEx(idHook As Integer, lpfn As HookProc, hMod As IntPtr, dwThreadId As Integer) As Integer
    End Function

    <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
    Private Shared Function GetModuleHandle(modulename As [String]) As IntPtr
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
    Private Shared Function SetWindowsHookExW(idHook As Integer, lpfn As HookProc, hmod As IntPtr, dwThreadID As UInteger) As IntPtr
    End Function


    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)>
    Protected Shared Function UnhookWindowsHookEx(idHook As Integer) As Integer
    End Function


    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
    Protected Shared Function CallNextHookEx(idHook As Integer, nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer
    End Function

    <DllImport("user32")>
    Protected Shared Function ToAscii(uVirtKey As Integer, uScanCode As Integer, lpbKeyState As Byte(), lpwTransKey As Byte(), fuState As Integer) As Integer
    End Function

    <DllImport("user32")>
    Protected Shared Function GetKeyboardState(pbKeyState As Byte()) As Integer
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
    Protected Shared Function GetKeyState(vKey As Integer) As Short
    End Function

    Protected Delegate Function HookProc(nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer


    Protected Const WH_MOUSE_LL As Integer = 14
    Protected Const WH_KEYBOARD_LL As Integer = 13

    Protected Const WH_MOUSE As Integer = 7
    Protected Const WH_KEYBOARD As Integer = 2
    Protected Const WM_MOUSEMOVE As Integer = &H200
    Protected Const WM_LBUTTONDOWN As Integer = &H201
    Protected Const WM_RBUTTONDOWN As Integer = &H204
    Protected Const WM_MBUTTONDOWN As Integer = &H207
    Protected Const WM_LBUTTONUP As Integer = &H202
    Protected Const WM_RBUTTONUP As Integer = &H205
    Protected Const WM_MBUTTONUP As Integer = &H208
    Protected Const WM_LBUTTONDBLCLK As Integer = &H203
    Protected Const WM_RBUTTONDBLCLK As Integer = &H206
    Protected Const WM_MBUTTONDBLCLK As Integer = &H209
    Protected Const WM_MOUSEWHEEL As Integer = &H20A
    Protected Const WM_KEYDOWN As Integer = &H100
    Protected Const WM_KEYUP As Integer = &H101
    Protected Const WM_SYSKEYDOWN As Integer = &H104
    Protected Const WM_SYSKEYUP As Integer = &H105

    Protected Const VK_SHIFT As Byte = &H10
    Protected Const VK_CAPITAL As Byte = &H14
    Protected Const VK_NUMLOCK As Byte = &H90

    Protected Const VK_LSHIFT As Byte = &HA0
    Protected Const VK_RSHIFT As Byte = &HA1
    Protected Const VK_LCONTROL As Byte = &HA2
    Protected Const VK_RCONTROL As Byte = &H3
    Protected Const VK_LALT As Byte = &HA4
    Protected Const VK_RALT As Byte = &HA5

    Protected Const LLKHF_ALTDOWN As Byte = &H20

#End Region

#Region "Private Variables"

    Protected _hookType As Integer
    Protected _handleToHook As Integer
    Public _isStarted As Boolean
    Protected _hookCallback As HookProc

#End Region

#Region "Properties"

    Public ReadOnly Property IsStarted() As Boolean
        Get
            Return _isStarted
        End Get
    End Property

#End Region

#Region "Constructor"

    Public Sub New()
        '绑定ApplicationExit事件
        '在应用程序关闭时发生的事件。用的委托。
        AddHandler Application.ApplicationExit, AddressOf Application_ApplicationExit
    End Sub

#End Region

#Region "Methods"

    Public Sub Start()

        If Not _isStarted AndAlso _hookType <> 0 Then

            '确保_hookCallback不是一个空的引用
            '如果是，GC会随机回收它，并且一个空的引用会爆出异常
            _hookCallback = New HookProc(AddressOf HookCallbackProcedure)
            Using curPro As Process = Process.GetCurrentProcess()
                Using curMod As ProcessModule = curPro.MainModule
                    _handleToHook = CInt(SetWindowsHookExW(_hookType, _hookCallback, GetModuleHandle(curMod.ModuleName), 0))
                End Using
            End Using
            ' 钩成功
            If _handleToHook <> 0 Then
                _isStarted = True

            End If
        End If

    End Sub

    Public Sub [Stop]()

        If _isStarted Then
            UnhookWindowsHookEx(_handleToHook)
            _isStarted = False
        End If

    End Sub

    ''' <summary>
    ''' 钩子回调函数
    ''' </summary>
    ''' <param name="nCode"></param>
    ''' <param name="wParam"></param>
    ''' <param name="lParam"></param>
    ''' <returns></returns>
    Protected Overridable Function HookCallbackProcedure(nCode As Integer, wParam As Int32, lParam As IntPtr) As Integer

        ' This method must be overriden by each extending hook  
        Return 0

    End Function
    ''' <summary>
    ''' 程序退出方法
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Protected Sub Application_ApplicationExit(sender As Object, e As EventArgs)

        If _isStarted Then
            [Stop]()
        End If

    End Sub

#End Region

End Class

''' <summary>  
''' 键盘钩子类
''' </summary>  
Public Class KeyboardHook
    Inherits GlobalHook

    Private events As New System.ComponentModel.EventHandlerList
#Region "Events"

    Public Event KeyDown As KeyEventHandler
    Public Event KeyUp As KeyEventHandler
    Public Event KeyPress As KeyPressEventHandler

#End Region

#Region "Constructor"

    Public Sub New()


        _hookType = WH_KEYBOARD_LL
    End Sub

#End Region

#Region "Methods"
    'https://blog.csdn.net/asciil/article/details/7195666
    Protected Overrides Function HookCallbackProcedure(nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer

        Dim handled As Boolean = False

        If nCode > -1 AndAlso (events("KeyDown") IsNot Nothing OrElse events("KeyUp") IsNot Nothing OrElse events("KeyPress") IsNot Nothing) Then

            Dim keyboardHookStruct As KeyboardHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(KeyboardHookStruct)), KeyboardHookStruct)

            ' Is Control being held down?  
            Dim control As Boolean = ((GetKeyState(VK_LCONTROL) And &H80) <> 0) OrElse ((GetKeyState(VK_RCONTROL) And &H80) <> 0)

            ' Is Shift being held down?  
            Dim shift As Boolean = ((GetKeyState(VK_LSHIFT) And &H80) <> 0) OrElse ((GetKeyState(VK_RSHIFT) And &H80) <> 0)

            ' Is Alt being held down?  
            Dim alt As Boolean = ((GetKeyState(VK_LALT) And &H80) <> 0) OrElse ((GetKeyState(VK_RALT) And &H80) <> 0)

            ' Is CapsLock on?  
            Dim capslock As Boolean = (GetKeyState(VK_CAPITAL) <> 0)

            ' Create event using keycode and control/shift/alt values found above  
            Dim e As New KeyEventArgs(DirectCast(keyboardHookStruct.vkCode Or (If(control, CInt(Keys.Control), 0)) Or (If(shift, CInt(Keys.Shift), 0)) Or (If(alt, CInt(Keys.Alt), 0)), Keys))

            ' Handle KeyDown and KeyUp events  
            Select Case wParam

                Case WM_KEYDOWN, WM_SYSKEYDOWN
                    If events("KeyDown") IsNot Nothing Then
                        RaiseEvent KeyDown(Me, e)
                        handled = handled OrElse e.Handled
                    End If
                    Exit Select
                Case WM_KEYUP, WM_SYSKEYUP
                    If events("KeyUp") IsNot Nothing Then
                        RaiseEvent KeyUp(Me, e)
                        handled = handled OrElse e.Handled
                    End If
                    Exit Select

            End Select

            ' Handle KeyPress event  
            If wParam = WM_KEYDOWN AndAlso Not handled AndAlso Not e.SuppressKeyPress AndAlso events("KeyPress") IsNot Nothing Then

                Dim keyState As Byte() = New Byte(255) {}
                Dim inBuffer As Byte() = New Byte(1) {}
                GetKeyboardState(keyState)

                If ToAscii(keyboardHookStruct.vkCode, keyboardHookStruct.scanCode, keyState, inBuffer, keyboardHookStruct.flags) = 1 Then

                    '	Dim key As Char = CChar(inBuffer(0))'修改为下面的句子。
                    Dim key As Char : key = Chr(inBuffer(0))
                    If (capslock Xor shift) AndAlso [Char].IsLetter(key) Then
                        key = [Char].ToUpper(key)
                    End If
                    Dim e2 As New KeyPressEventArgs(key)
                    RaiseEvent KeyPress(Me, e2)

                    handled = handled OrElse e.Handled

                End If

            End If
        End If

        If handled Then
            Return 1
        Else
            Return CallNextHookEx(_handleToHook, nCode, wParam, lParam)
        End If

    End Function

#End Region

End Class

''' <summary>  
''' 鼠标钩子类
''' </summary>  
Public Class MouseHook
    Inherits GlobalHook

    Private events As New System.ComponentModel.EventHandlerList
#Region "MouseEventType Enum"

    Private Enum MouseEventType
        None
        MouseDown
        MouseUp
        DoubleClick
        MouseWheel
        MouseMove
    End Enum

#End Region

#Region "Events"
    '''' <summary>
    '''' 鼠标按下事件
    '''' </summary>
    'Public Event MouseDown As MouseEventHandler
    '''' <summary>
    '''' 送开鼠标事件
    '''' </summary>
    'Public Event MouseUp As MouseEventHandler
    '''' <summary>
    '''' 鼠标移动事件
    '''' </summary>
    'Public Event MouseMove As MouseEventHandler
    '''' <summary>
    '''' 鼠标滚轮事件
    '''' </summary>
    'Public Event MouseWheel As MouseEventHandler
    '''' <summary>
    '''' 鼠标单击事件
    '''' </summary>
    'Public Event Click As EventHandler
    '''' <summary>
    '''' 鼠标双击事件
    '''' </summary>
    'Public Event DoubleClick As EventHandler

    ''' <summary>鼠标按下事件</summary>
    Public Custom Event MouseDown As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            events.AddHandler("MouseDown", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            events.RemoveHandler("MouseDown", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(events("MouseDown"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标松开事件</summary>
    Public Custom Event MouseUp As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            events.AddHandler("MouseUp", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            events.RemoveHandler("MouseUp", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(events("MouseUp"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标移动事件</summary>
    Public Custom Event MouseMove As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            events.AddHandler("MouseMove", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            events.RemoveHandler("MouseMove", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(events("MouseMove"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event


    ''' <summary>鼠标移动事件</summary>
    Public Custom Event MouseWheel As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            events.AddHandler("MouseWheel", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            events.RemoveHandler("MouseWheel", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(events("MouseWheel"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标移动事件</summary>
    Public Custom Event Click As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            events.AddHandler("Click", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            events.RemoveHandler("Click", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(events("Click"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event

    ''' <summary>鼠标移动事件</summary>
    Public Custom Event DoubleClick As MouseEventHandler
        AddHandler(ByVal value As MouseEventHandler)
            events.AddHandler("DoubleClick", value)
        End AddHandler
        RemoveHandler(ByVal value As MouseEventHandler)
            events.RemoveHandler("DoubleClick", value)
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
            Dim eh As MouseEventHandler = TryCast(events("DoubleClick"), MouseEventHandler)
            If eh IsNot Nothing Then eh.Invoke(sender, e)
        End RaiseEvent
    End Event


#End Region

#Region "Constructor"

    Public Sub New()


        _hookType = WH_MOUSE_LL
    End Sub

#End Region

#Region "Methods"
    ''' <summary>
    ''' 钩子回调函数
    ''' </summary>
    ''' <param name="nCode"></param>
    ''' <param name="wParam"></param>
    ''' <param name="lParam"></param>
    ''' <returns></returns>
    Protected Overrides Function HookCallbackProcedure(nCode As Integer, wParam As Integer, lParam As IntPtr) As Integer

        If nCode > -1 AndAlso (events("MouseDown") IsNot Nothing OrElse events("MouseUp") IsNot Nothing OrElse events("MouseMove") IsNot Nothing) Then

            Dim mouseHookStruct As MouseLLHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(MouseLLHookStruct)), MouseLLHookStruct)

            Dim button As MouseButtons = GetButton(wParam)
            Dim eventType As MouseEventType = GetEventType(wParam) '定义的鼠标事件类型

            ' Dim e As New MouseEventArgs(button, (If(eventType = MouseEventType.DoubleClick, 2, 1)), mouseHookStruct.pt.x, mouseHookStruct.pt.y, (If(eventType = MouseEventType.MouseWheel, CShort((mouseHookStruct.mouseData >> 16) And &HFFFF), 0)))



            '******************改写成上面的Dim e As New MouseEventArgs语句和if语句如下：
            'If eventType = MouseEventType.DoubleClick Then
            '    eventType = 2
            'Else
            '    eventType = 1
            'End If

            ''本段代码CLE添加，模仿C#的Short从Int弃位转换
            Static int As Integer : int = (mouseHookStruct.mouseData >> 16) And &HFFFF '定义一个静态变量

            If eventType = MouseEventType.MouseWheel Then
                If int > Short.MaxValue Then mouseHookStruct.mouseData = int - 65536 Else mouseHookStruct.mouseData = int
            Else
                mouseHookStruct.mouseData = 0
            End If
            Dim e As New MouseEventArgs(button, (If(eventType = MouseEventType.DoubleClick, 2, 1)), mouseHookStruct.pt.x, mouseHookStruct.pt.y, mouseHookStruct.mouseData)

            '原函数构造函数MouseEventArgs(MouseButtons, Int32, Int32, Int32, Int32)
            '  button()  '获取曾按下的是哪个鼠标按钮。
            '  Clicks()            '获取按下并释放鼠标按钮的次数。
            ' Delta()            '获取鼠标轮已转动的制动器数的有符号计数乘以 WHEEL_DELTA 常数。 制动器是鼠标轮的一个凹口。
            ' Location()            '获取鼠标在产生鼠标事件时的位置。
            '  X()            '获取鼠标在产生鼠标事件时的 x 坐标。           
            'Y()            '获取鼠标在产生鼠标事件时的 y 坐标。
            '  Dim e As MouseEventArgs = New MouseEventArgs(button, eventType, mouseHookStruct.pt.x, mouseHookStruct.pt.y, mouseHookStruct.mouseData)

            '*************************改写完毕。



            ' Prevent multiple Right Click events (this probably happens for popup menus)  
            If button = MouseButtons.Right AndAlso mouseHookStruct.flags <> 0 Then
                eventType = MouseEventType.None
            End If

            Select Case eventType
                Case MouseEventType.MouseDown
                    RaiseEvent MouseDown(Me, e)

                    Exit Select
                Case MouseEventType.MouseUp
                    RaiseEvent Click(Me, e)
                    RaiseEvent MouseUp(Me, e)
                    Exit Select
                Case MouseEventType.DoubleClick
                    RaiseEvent DoubleClick(Me, e)
                    Exit Select
                Case MouseEventType.MouseWheel
                    RaiseEvent MouseWheel(Me, e)
                    Exit Select
                Case MouseEventType.MouseMove
                    RaiseEvent MouseMove(Me, e)
                    Exit Select
                Case Else
                    Exit Select

            End Select
        End If

        Return CallNextHookEx(_handleToHook, nCode, wParam, lParam)

    End Function

    Private Function GetButton(wParam As Int32) As MouseButtons

        Select Case wParam

            Case WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK
                Return MouseButtons.Left
            Case WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK
                Return MouseButtons.Right
            Case WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MBUTTONDBLCLK
                Return MouseButtons.Middle
            Case Else
                Return MouseButtons.None

        End Select

    End Function

    Private Function GetEventType(wParam As Int32) As MouseEventType

        Select Case wParam

            Case WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN
                Return MouseEventType.MouseDown
            Case WM_LBUTTONUP, WM_RBUTTONUP, WM_MBUTTONUP
                Return MouseEventType.MouseUp
            Case WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK
                Return MouseEventType.DoubleClick
            Case WM_MOUSEWHEEL
                Return MouseEventType.MouseWheel
            Case WM_MOUSEMOVE
                Return MouseEventType.MouseMove
            Case Else
                Return MouseEventType.None

        End Select
    End Function

#End Region

End Class

''' <summary>  
''' 模拟键盘事件类
''' </summary>  
Public NotInheritable Class KeyboardSimulator
    Private Sub New()
    End Sub

#Region "Standard Keyboard Shortcuts Enum"

    ''' <summary>  
    '''  标准的人体工程键盘快捷键 
    ''' </summary>  
    Public Enum StandardShortcut
        Copy
        Cut
        Paste
        SelectAll
        Save
        Open
        [New]
        Close
        Print
    End Enum

#End Region

#Region "Windows API Code"

    Const KEYEVENTF_EXTENDEDKEY As Integer = &H1
    Const KEYEVENTF_KEYUP As Integer = &H2

    <DllImport("user32.dll")>
    Private Shared Sub keybd_event(key As Byte, scan As Byte, flags As Integer, extraInfo As Integer)
    End Sub

#End Region

#Region "Methods"

    Public Shared Sub KeyDown(key As Keys)
        keybd_event(ParseKey(key), 0, 0, 0)
    End Sub

    Public Shared Sub KeyUp(key As Keys)
        keybd_event(ParseKey(key), 0, KEYEVENTF_KEYUP, 0)
    End Sub

    Public Shared Sub KeyPress(key As Keys)
        KeyDown(key)
        KeyUp(key)
    End Sub

    Public Shared Sub SimulateStandardShortcut(shortcut As StandardShortcut)
        Select Case shortcut
            Case StandardShortcut.Copy
                KeyDown(Keys.Control)
                KeyPress(Keys.C)
                KeyUp(Keys.Control)
                Exit Select
            Case StandardShortcut.Cut
                KeyDown(Keys.Control)
                KeyPress(Keys.X)
                KeyUp(Keys.Control)
                Exit Select
            Case StandardShortcut.Paste
                KeyDown(Keys.Control)
                KeyPress(Keys.V)
                KeyUp(Keys.Control)
                Exit Select
            Case StandardShortcut.SelectAll
                KeyDown(Keys.Control)
                KeyPress(Keys.A)
                KeyUp(Keys.Control)
                Exit Select
            Case StandardShortcut.Save
                KeyDown(Keys.Control)
                KeyPress(Keys.S)
                KeyUp(Keys.Control)
                Exit Select
            Case StandardShortcut.Open
                KeyDown(Keys.Control)
                KeyPress(Keys.O)
                KeyUp(Keys.Control)
                Exit Select
            Case StandardShortcut.[New]
                KeyDown(Keys.Control)
                KeyPress(Keys.N)
                KeyUp(Keys.Control)
                Exit Select
            Case StandardShortcut.Close
                KeyDown(Keys.Alt)
                KeyPress(Keys.F4)
                KeyUp(Keys.Alt)
                Exit Select
            Case StandardShortcut.Print
                KeyDown(Keys.Control)
                KeyPress(Keys.P)
                KeyUp(Keys.Control)
                Exit Select
        End Select
    End Sub

    Private Shared Function ParseKey(key As Keys) As Byte

        ' Alt, Shift, and Control need to be changed for API function to work with them  
        Select Case key
            Case Keys.Alt
                Return CByte(18)
            Case Keys.Control
                Return CByte(17)
            Case Keys.Shift
                Return CByte(16)
            Case Else
                Return CByte(key)
        End Select

    End Function

#End Region

End Class


''' <summary>  
''' 模拟鼠标事件类
''' </summary>  
Public NotInheritable Class MouseSimulator
    Private Sub New()
    End Sub
    ''' <summary>  
    '''获取鼠标在屏幕上的x，y坐标， And X, Y point on the screen  
    ''' </summary>  
    Public Structure MousePoint

        Public Sub New(p As Point)
            X = p.X
            Y = p.Y
        End Sub

        Public X As Integer
        Public Y As Integer

        Public Shared Widening Operator CType(p As MousePoint) As Point
            Return New Point(p.X, p.Y)
        End Operator

    End Structure

    ''' <summary>  
    ''' 可以按下的鼠标类型，Mouse buttons that can be pressed  
    ''' </summary>  
    Public Enum MouseButton
        Left = &H2
        Right = &H8
        Middle = &H20
    End Enum

#Region "Windows API Code"

    <DllImport("user32.dll")>
    Private Shared Function ShowCursor(show As Boolean) As Integer
    End Function

    <DllImport("user32.dll")>
    Private Shared Sub mouse_event(flags As Integer, dX As Integer, dY As Integer, buttons As Integer, extraInfo As Integer)
    End Sub

    Const MOUSEEVENTF_MOVE As Integer = &H1
    Const MOUSEEVENTF_LEFTDOWN As Integer = &H2
    Const MOUSEEVENTF_LEFTUP As Integer = &H4
    Const MOUSEEVENTF_RIGHTDOWN As Integer = &H8
    Const MOUSEEVENTF_RIGHTUP As Integer = &H10
    Const MOUSEEVENTF_MIDDLEDOWN As Integer = &H20
    Const MOUSEEVENTF_MIDDLEUP As Integer = &H40
    Const MOUSEEVENTF_WHEEL As Integer = &H800
    Const MOUSEEVENTF_ABSOLUTE As Integer = &H8000

#End Region

#Region "Properties"

    ''' <summary>  
    ''' 获取或设置表示鼠标X和Y坐标的结构，Gets or sets a structure that represents both X and Y mouse coordinates  
    ''' </summary>  
    Public Shared Property Position() As MousePoint
        Get
            Return New MousePoint(Cursor.Position)
        End Get
        Set(value As MousePoint)
            Cursor.Position = value
        End Set
    End Property

    ''' <summary>  
    '''获取或设置鼠标的x坐标， Gets or sets only the mouse's x coordinate  
    ''' </summary>  
    Public Shared Property X() As Integer
        Get
            Return Cursor.Position.X
        End Get
        Set(value As Integer)
            Cursor.Position = New Point(value, Y)
        End Set
    End Property

    ''' <summary>  
    '''获取或设置鼠标的y坐标 Gets or sets only the mouse's y coordinate  
    ''' </summary>  
    Public Shared Property Y() As Integer
        Get
            Return Cursor.Position.Y
        End Get
        Set(value As Integer)
            Cursor.Position = New Point(X, value)
        End Set
    End Property

#End Region

#Region "Methods"

    ''' <summary>  
    ''' 按下鼠标按钮，Press a mouse button down  
    ''' </summary>  
    ''' <param name="button"></param>  
    Public Shared Sub MouseDown(button As MouseButton)
        mouse_event(CInt(button), 0, 0, 0, 0)
    End Sub

    Public Shared Sub MouseDown(button As MouseButtons)
        Select Case button
            Case MouseButtons.Left
                MouseDown(MouseButton.Left)
                Exit Select
            Case MouseButtons.Middle
                MouseDown(MouseButton.Middle)
                Exit Select
            Case MouseButtons.Right
                MouseDown(MouseButton.Right)
                Exit Select
        End Select
    End Sub

    ''' <summary>  
    ''' 抬起鼠标，Let a mouse button up  
    ''' </summary>  
    ''' <param name="button"></param>  
    Public Shared Sub MouseUp(button As MouseButton)
        mouse_event(CInt(button) * 2, 0, 0, 0, 0)
    End Sub

    Public Shared Sub MouseUp(button As MouseButtons)
        Select Case button
            Case MouseButtons.Left
                MouseUp(MouseButton.Left)
                Exit Select
            Case MouseButtons.Middle
                MouseUp(MouseButton.Middle)
                Exit Select
            Case MouseButtons.Right
                MouseUp(MouseButton.Right)
                Exit Select
        End Select
    End Sub

    ''' <summary>  
    ''' 点击鼠标按钮(先向下再向上)，Click a mouse button (down then up)  
    ''' </summary>  
    ''' <param name="button"></param>  
    Public Shared Sub Click(button As MouseButton)
        MouseDown(button)
        MouseUp(button)
    End Sub

    Public Shared Sub Click(button As MouseButtons)
        Select Case button
            Case MouseButtons.Left
                Click(MouseButton.Left)
                Exit Select
            Case MouseButtons.Middle
                Click(MouseButton.Middle)
                Exit Select
            Case MouseButtons.Right
                Click(MouseButton.Right)
                Exit Select
        End Select
    End Sub

    ''' <summary>  
    ''' 双击鼠标按钮(向下然后向上两次)，Double click a mouse button (down then up twice)  
    ''' </summary>  
    ''' <param name="button"></param>  
    Public Shared Sub DoubleClick(button As MouseButton)
        Click(button)
        Click(button)
    End Sub

    Public Shared Sub DoubleClick(button As MouseButtons)
        Select Case button
            Case MouseButtons.Left
                DoubleClick(MouseButton.Left)
                Exit Select
            Case MouseButtons.Middle
                DoubleClick(MouseButton.Middle)
                Exit Select
            Case MouseButtons.Right
                DoubleClick(MouseButton.Right)
                Exit Select
        End Select
    End Sub

    ''' <summary>  
    ''' 显示当前应用程序上的光标，Show a hidden current on currently application  
    ''' </summary>  
    Public Shared Sub Show()
        ShowCursor(True)
    End Sub

    ''' <summary>  
    ''' 只在当前应用程序的窗体上隐藏鼠标光标，Hide mouse cursor only on current application's forms  
    ''' </summary>  
    Public Shared Sub Hide()
        ShowCursor(False)
    End Sub

#End Region

End Class
#End Region